home *** CD-ROM | disk | FTP | other *** search
/ Software of the Month Club 2000 October / Software of the Month - Ultimate Collection Shareware 277.iso / pc / PROGRAMS / UTILITY / WINLINUX / DATA1.CAB / programs_-_include / ASM-ARM / PROC-ARM.{21 / PGTABLE.H < prev    next >
C/C++ Source or Header  |  1999-09-17  |  18KB  |  706 lines

  1. /*
  2.  * linux/include/asm-arm/proc-armv/pgtable.h
  3.  *
  4.  * Copyright (C) 1995, 1996, 1997 Russell King
  5.  *
  6.  * 12-01-1997    RMK    Altered flushing routines to use function pointers
  7.  *            now possible to combine ARM6, ARM7 and StrongARM versions.
  8.  */
  9. #ifndef __ASM_PROC_PGTABLE_H
  10. #define __ASM_PROC_PGTABLE_H
  11.  
  12. #include <asm/arch/mmu.h>
  13. #include <asm/arch/processor.h>        /* For TASK_SIZE */
  14.  
  15. #define LIBRARY_TEXT_START 0x0c000000
  16.  
  17. /*
  18.  * Cache flushing...
  19.  */
  20. #define flush_cache_all()                        \
  21.     processor.u.armv3v4._flush_cache_all()
  22.  
  23. #define flush_cache_mm(_mm)                        \
  24.     do {                                \
  25.         if ((_mm) == current->mm)                \
  26.             processor.u.armv3v4._flush_cache_all();        \
  27.     } while (0)
  28.  
  29. #define flush_cache_range(_mm,_start,_end)                \
  30.     do {                                \
  31.         if ((_mm) == current->mm)                \
  32.             processor.u.armv3v4._flush_cache_area        \
  33.                 ((_start), (_end), 1);            \
  34.     } while (0)
  35.  
  36. #define flush_cache_page(_vma,_vmaddr)                    \
  37.     do {                                \
  38.         if ((_vma)->vm_mm == current->mm)            \
  39.             processor.u.armv3v4._flush_cache_area        \
  40.                 ((_vmaddr), (_vmaddr) + PAGE_SIZE,    \
  41.                  ((_vma)->vm_flags & VM_EXEC) ? 1 : 0);    \
  42.     } while (0)
  43.  
  44. #define flush_icache_range(_start,_end)                    \
  45.     processor.u.armv3v4._flush_icache_area((_start), (_end))
  46.  
  47. /*
  48.  * We don't have a MEMC chip...
  49.  */
  50. #define update_memc_all()        do { } while (0)
  51. #define update_memc_task(tsk)        do { } while (0)
  52. #define update_memc_mm(mm)        do { } while (0)
  53. #define update_memc_addr(mm,addr,pte)    do { } while (0)
  54.  
  55. /*
  56.  * This flushes back any buffered write data.  We have to clean and flush the entries
  57.  * in the cache for this page.  Is it necessary to invalidate the I-cache?
  58.  */
  59. #define flush_page_to_ram(_page)                    \
  60.     processor.u.armv3v4._flush_ram_page ((_page) & PAGE_MASK);
  61.  
  62. /*
  63.  * Make the page uncacheable (must flush page beforehand).
  64.  */
  65. #define uncache_page(_page)                        \
  66.     processor.u.armv3v4._flush_ram_page ((_page) & PAGE_MASK);
  67.  
  68. /*
  69.  * TLB flushing:
  70.  *
  71.  *  - flush_tlb() flushes the current mm struct TLBs
  72.  *  - flush_tlb_all() flushes all processes TLBs
  73.  *  - flush_tlb_mm(mm) flushes the specified mm context TLB's
  74.  *  - flush_tlb_page(vma, vmaddr) flushes one page
  75.  *  - flush_tlb_range(mm, start, end) flushes a range of pages
  76.  *
  77.  * GCC uses conditional instructions, and expects the assembler code to do so as well.
  78.  *
  79.  * We drain the write buffer in here to ensure that the page tables in ram
  80.  * are really up to date.  It is more efficient to do this here...
  81.  */
  82. #define flush_tlb() flush_tlb_all()
  83.  
  84. #define flush_tlb_all()                                \
  85.     processor.u.armv3v4._flush_tlb_all()
  86.  
  87. #define flush_tlb_mm(_mm)                            \
  88.     do {                                    \
  89.         if ((_mm) == current->mm)                    \
  90.             processor.u.armv3v4._flush_tlb_all();            \
  91.     } while (0)
  92.  
  93. #define flush_tlb_range(_mm,_start,_end)                    \
  94.     do {                                    \
  95.         if ((_mm) == current->mm)                    \
  96.             processor.u.armv3v4._flush_tlb_area            \
  97.                 ((_start), (_end), 1);                \
  98.     } while (0)
  99.  
  100. #define flush_tlb_page(_vma,_vmaddr)                        \
  101.     do {                                    \
  102.         if ((_vma)->vm_mm == current->mm)                \
  103.             processor.u.armv3v4._flush_tlb_area            \
  104.                 ((_vmaddr), (_vmaddr) + PAGE_SIZE,        \
  105.                  ((_vma)->vm_flags & VM_EXEC) ? 1 : 0);        \
  106.     } while (0)
  107.  
  108. /*
  109.  * Since the page tables are in cached memory, we need to flush the dirty
  110.  * data cached entries back before we flush the tlb...  This is also useful
  111.  * to flush out the SWI instruction for signal handlers...
  112.  */
  113. #define __flush_entry_to_ram(entry)                        \
  114.     processor.u.armv3v4._flush_cache_entry((unsigned long)(entry))
  115.  
  116. #define __flush_pte_to_ram(entry)                        \
  117.     processor.u.armv3v4._flush_cache_pte((unsigned long)(entry))
  118.  
  119. /* PMD_SHIFT determines the size of the area a second-level page table can map */
  120. #define PMD_SHIFT       20
  121. #define PMD_SIZE        (1UL << PMD_SHIFT)
  122. #define PMD_MASK        (~(PMD_SIZE-1))
  123.  
  124. /* PGDIR_SHIFT determines what a third-level page table entry can map */
  125. #define PGDIR_SHIFT     20
  126. #define PGDIR_SIZE      (1UL << PGDIR_SHIFT)
  127. #define PGDIR_MASK      (~(PGDIR_SIZE-1))
  128.  
  129. /*
  130.  * entries per page directory level: the sa110 is two-level, so
  131.  * we don't really have any PMD directory physically.
  132.  */
  133. #define PTRS_PER_PTE    256
  134. #define PTRS_PER_PMD    1
  135. #define PTRS_PER_PGD    4096
  136. #define USER_PTRS_PER_PGD    (TASK_SIZE/PGDIR_SIZE)
  137.  
  138. /* Just any arbitrary offset to the start of the vmalloc VM area: the
  139.  * current 8MB value just means that there will be a 8MB "hole" after the
  140.  * physical memory until the kernel virtual memory starts.  That means that
  141.  * any out-of-bounds memory accesses will hopefully be caught.
  142.  * The vmalloc() routines leaves a hole of 4kB between each vmalloced
  143.  * area for the same reason. ;)
  144.  */
  145. #define VMALLOC_OFFSET      (8*1024*1024)
  146. #define VMALLOC_START      (((unsigned long)high_memory + VMALLOC_OFFSET) & ~(VMALLOC_OFFSET-1))
  147. #define VMALLOC_VMADDR(x) ((unsigned long)(x))
  148. #define VMALLOC_END       (PAGE_OFFSET + 0x10000000)
  149.  
  150. /* PMD types (actually level 1 descriptor) */
  151. #define PMD_TYPE_MASK        0x0003
  152. #define PMD_TYPE_FAULT        0x0000
  153. #define PMD_TYPE_TABLE        0x0001
  154. #define PMD_TYPE_SECT        0x0002
  155. #define PMD_UPDATABLE        0x0010
  156. #define PMD_SECT_CACHEABLE    0x0008
  157. #define PMD_SECT_BUFFERABLE    0x0004
  158. #define PMD_SECT_AP_WRITE    0x0400
  159. #define PMD_SECT_AP_READ    0x0800
  160. #define PMD_DOMAIN(x)        ((x) << 5)
  161.  
  162. /* PTE types (actially level 2 descriptor) */
  163. #define PTE_TYPE_MASK    0x0003
  164. #define PTE_TYPE_FAULT    0x0000
  165. #define PTE_TYPE_LARGE    0x0001
  166. #define PTE_TYPE_SMALL    0x0002
  167. #define PTE_AP_READ    0x0aa0
  168. #define PTE_AP_WRITE    0x0550
  169. #define PTE_CACHEABLE    0x0008
  170. #define PTE_BUFFERABLE    0x0004
  171.  
  172. /* Domains */
  173. #define DOMAIN_USER    0
  174. #define DOMAIN_KERNEL    1
  175. #define DOMAIN_TABLE    1
  176. #define DOMAIN_IO    2
  177.  
  178. #define _PAGE_CHG_MASK  (0xfffff00c | PTE_TYPE_MASK)
  179.  
  180. /*
  181.  * We define the bits in the page tables as follows:
  182.  *  PTE_BUFFERABLE    page is dirty
  183.  *  PTE_AP_WRITE    page is writable
  184.  *  PTE_AP_READ        page is a young (unsetting this causes faults for any access)
  185.  *  PTE_CACHEABLE       page is readable
  186.  *
  187.  * A page will not be made writable without the dirty bit set.
  188.  * It is not legal to have a writable non-dirty page though (it breaks).
  189.  *
  190.  * A readable page is marked as being cacheable.
  191.  * Youngness is indicated by hardware read.  If the page is old,
  192.  * then we will fault and make the page young again.
  193.  */
  194. #define _PTE_YOUNG    PTE_AP_READ
  195. #define _PTE_DIRTY    PTE_BUFFERABLE
  196. #define _PTE_READ    PTE_CACHEABLE
  197. #define _PTE_WRITE    PTE_AP_WRITE
  198.  
  199. #define PAGE_NONE       __pgprot(PTE_TYPE_SMALL | _PTE_YOUNG)
  200. #define PAGE_SHARED     __pgprot(PTE_TYPE_SMALL | _PTE_YOUNG | _PTE_READ | _PTE_WRITE)
  201. #define PAGE_COPY       __pgprot(PTE_TYPE_SMALL | _PTE_YOUNG | _PTE_READ)
  202. #define PAGE_READONLY   __pgprot(PTE_TYPE_SMALL | _PTE_YOUNG | _PTE_READ)
  203. #define PAGE_KERNEL     __pgprot(PTE_TYPE_SMALL | _PTE_READ  | _PTE_DIRTY | _PTE_WRITE)
  204.  
  205. #define _PAGE_USER_TABLE    (PMD_TYPE_TABLE | PMD_DOMAIN(DOMAIN_USER))
  206. #define _PAGE_KERNEL_TABLE    (PMD_TYPE_TABLE | PMD_DOMAIN(DOMAIN_KERNEL))
  207.  
  208. /*
  209.  * The arm can't do page protection for execute, and considers that the same are read.
  210.  * Also, write permissions imply read permissions. This is the closest we can get..
  211.  */
  212. #define __P000  PAGE_NONE
  213. #define __P001  PAGE_READONLY
  214. #define __P010  PAGE_COPY
  215. #define __P011  PAGE_COPY
  216. #define __P100  PAGE_READONLY
  217. #define __P101  PAGE_READONLY
  218. #define __P110  PAGE_COPY
  219. #define __P111  PAGE_COPY
  220.  
  221. #define __S000  PAGE_NONE
  222. #define __S001  PAGE_READONLY
  223. #define __S010  PAGE_SHARED
  224. #define __S011  PAGE_SHARED
  225. #define __S100  PAGE_READONLY
  226. #define __S101  PAGE_READONLY
  227. #define __S110  PAGE_SHARED
  228. #define __S111  PAGE_SHARED
  229.  
  230. #undef TEST_VERIFY_AREA
  231.  
  232. /*
  233.  * BAD_PAGETABLE is used when we need a bogus page-table, while
  234.  * BAD_PAGE is used for a bogus page.
  235.  *
  236.  * ZERO_PAGE is a global shared page that is always zero: used
  237.  * for zero-mapped memory areas etc..
  238.  */
  239. extern pte_t __bad_page(void);
  240. extern pte_t * __bad_pagetable(void);
  241. extern unsigned long *empty_zero_page;
  242.  
  243. #define BAD_PAGETABLE __bad_pagetable()
  244. #define BAD_PAGE __bad_page()
  245. #define ZERO_PAGE ((unsigned long) empty_zero_page)
  246.  
  247. /* number of bits that fit into a memory pointer */
  248. #define BYTES_PER_PTR            (sizeof(unsigned long))
  249. #define BITS_PER_PTR                    (8*BYTES_PER_PTR)
  250.  
  251. /* to align the pointer to a pointer address */
  252. #define PTR_MASK                        (~(sizeof(void*)-1))
  253.  
  254. /* sizeof(void*)==1<<SIZEOF_PTR_LOG2 */
  255. #define SIZEOF_PTR_LOG2                 2
  256.  
  257. /* to find an entry in a page-table */
  258. #define PAGE_PTR(address) \
  259. ((unsigned long)(address)>>(PAGE_SHIFT-SIZEOF_PTR_LOG2)&PTR_MASK&~PAGE_MASK)
  260.  
  261. /* to set the page-dir */
  262. #define SET_PAGE_DIR(tsk,pgdir)                    \
  263. do {                                \
  264.     tsk->tss.memmap = __virt_to_phys((unsigned long)pgdir);    \
  265.     if ((tsk) == current)                    \
  266.         __asm__ __volatile__(                \
  267.         "mcr%?    p15, 0, %0, c2, c0, 0\n"        \
  268.         : : "r" (tsk->tss.memmap));            \
  269. } while (0)
  270.  
  271. extern __inline__ int pte_none(pte_t pte)
  272. {
  273.     return !pte_val(pte);
  274. }
  275.  
  276. #define pte_clear(ptep)    set_pte(ptep, __pte(0))
  277.  
  278. extern __inline__ int pte_present(pte_t pte)
  279. {
  280. #if 0
  281.     /* This is what it really does, the else
  282.        part is just to make it easier for the compiler */
  283.     switch (pte_val(pte) & PTE_TYPE_MASK) {
  284.     case PTE_TYPE_LARGE:
  285.     case PTE_TYPE_SMALL:
  286.         return 1;
  287.     default:
  288.         return 0;
  289.     }
  290. #else
  291.     return ((pte_val(pte) + 1) & 2);
  292. #endif
  293. }
  294.  
  295. extern __inline__ int pmd_none(pmd_t pmd)
  296. {
  297.     return !pmd_val(pmd);
  298. }
  299.  
  300. #define pmd_clear(pmdp) set_pmd(pmdp, __pmd(0))
  301.  
  302. extern __inline__ int pmd_bad(pmd_t pmd)
  303. {
  304. #if 0
  305.     /* This is what it really does, the else
  306.        part is just to make it easier for the compiler */
  307.     switch (pmd_val(pmd) & PMD_TYPE_MASK) {
  308.     case PMD_TYPE_FAULT:
  309.     case PMD_TYPE_TABLE:
  310.         return 0;
  311.     default:
  312.         return 1;
  313.     }
  314. #else
  315.     return pmd_val(pmd) & 2;
  316. #endif
  317. }
  318.  
  319. extern __inline__ int pmd_present(pmd_t pmd)
  320. {
  321. #if 0
  322.     /* This is what it really does, the else
  323.        part is just to make it easier for the compiler */
  324.     switch (pmd_val(pmd) & PMD_TYPE_MASK) {
  325.     case PMD_TYPE_TABLE:
  326.         return 1;
  327.     default:
  328.         return 0;
  329.     }
  330. #else
  331.     return ((pmd_val(pmd) + 1) & 2);
  332. #endif
  333. }
  334.  
  335. /*
  336.  * The "pgd_xxx()" functions here are trivial for a folded two-level
  337.  * setup: the pgd is never bad, and a pmd always exists (as it's folded
  338.  * into the pgd entry)
  339.  */
  340. #define pgd_none(pgd)        (0)
  341. #define pgd_bad(pgd)        (0)
  342. #define pgd_present(pgd)    (1)
  343. #define pgd_clear(pgdp)
  344.  
  345. /*
  346.  * The following only work if pte_present() is true.
  347.  * Undefined behaviour if not..
  348.  */
  349. #define pte_read(pte)        (1)
  350. #define pte_exec(pte)        (1)
  351.  
  352. extern __inline__ int pte_write(pte_t pte)
  353. {
  354.     return pte_val(pte) & _PTE_WRITE;
  355. }
  356.  
  357. extern __inline__ int pte_dirty(pte_t pte)
  358. {
  359.     return pte_val(pte) & _PTE_DIRTY;
  360. }
  361.  
  362. extern __inline__ int pte_young(pte_t pte)
  363. {
  364.     return pte_val(pte) & _PTE_YOUNG;
  365. }
  366.  
  367. extern __inline__ pte_t pte_wrprotect(pte_t pte)
  368. {
  369.     pte_val(pte) &= ~_PTE_WRITE;
  370.     return pte;
  371. }
  372.  
  373. extern __inline__ pte_t pte_nocache(pte_t pte)
  374. {
  375.     pte_val(pte) &= ~PTE_CACHEABLE;
  376.     return pte;
  377. }
  378.  
  379. extern __inline__ pte_t pte_mkclean(pte_t pte)
  380. {
  381.     pte_val(pte) &= ~_PTE_DIRTY;
  382.     return pte;
  383. }
  384.  
  385. extern __inline__ pte_t pte_mkold(pte_t pte)
  386. {
  387.     pte_val(pte) &= ~_PTE_YOUNG;
  388.     return pte;
  389. }
  390.  
  391. extern __inline__ pte_t pte_mkwrite(pte_t pte)
  392. {
  393.     pte_val(pte) |= _PTE_WRITE;
  394.     return pte;
  395. }
  396.  
  397. extern __inline__ pte_t pte_mkdirty(pte_t pte)
  398. {
  399.     pte_val(pte) |= _PTE_DIRTY;
  400.     return pte;
  401. }
  402.  
  403. extern __inline__ pte_t pte_mkyoung(pte_t pte)
  404. {
  405.     pte_val(pte) |= _PTE_YOUNG;
  406.     return pte;
  407. }
  408.  
  409. /*
  410.  * The following are unable to be implemented on this MMU
  411.  */
  412. #if 0
  413. extern __inline__ pte_t pte_rdprotect(pte_t pte)
  414. {
  415.     pte_val(pte) &= ~(PTE_CACHEABLE|PTE_AP_READ);
  416.     return pte;
  417. }
  418.  
  419. extern __inline__ pte_t pte_exprotect(pte_t pte)
  420. {
  421.     pte_val(pte) &= ~(PTE_CACHEABLE|PTE_AP_READ);
  422.     return pte;
  423. }
  424.  
  425. extern __inline__ pte_t pte_mkread(pte_t pte)
  426. {
  427.     pte_val(pte) |= PTE_CACHEABLE;
  428.     return pte;
  429. }
  430.  
  431. extern __inline__ pte_t pte_mkexec(pte_t pte)
  432. {
  433.     pte_val(pte) |= PTE_CACHEABLE;
  434.     return pte;
  435. }
  436. #endif
  437.  
  438. /*
  439.  * Conversion functions: convert a page and protection to a page entry,
  440.  * and a page entry and page directory to the page they refer to.
  441.  */
  442. extern __inline__ pte_t mk_pte(unsigned long page, pgprot_t pgprot)
  443. {
  444.     pte_t pte;
  445.     pte_val(pte) = __virt_to_phys(page) | pgprot_val(pgprot);
  446.     return pte;
  447. }
  448.  
  449. /* This takes a physical page address that is used by the remapping functions */
  450. extern __inline__ pte_t mk_pte_phys(unsigned long physpage, pgprot_t pgprot)
  451. {
  452.     pte_t pte;
  453.     pte_val(pte) = physpage + pgprot_val(pgprot);
  454.     return pte;
  455. }
  456.  
  457. extern __inline__ pte_t pte_modify(pte_t pte, pgprot_t newprot)
  458. {
  459.     pte_val(pte) = (pte_val(pte) & _PAGE_CHG_MASK) | pgprot_val(newprot);
  460.     return pte;
  461. }
  462.  
  463. extern __inline__ void set_pte(pte_t *pteptr, pte_t pteval)
  464. {
  465.     *pteptr = pteval;
  466.     __flush_pte_to_ram(pteptr);
  467. }
  468.  
  469. extern __inline__ unsigned long pte_page(pte_t pte)
  470. {
  471.     return __phys_to_virt(pte_val(pte) & PAGE_MASK);
  472. }
  473.  
  474. extern __inline__ pmd_t mk_user_pmd(pte_t *ptep)
  475. {
  476.     pmd_t pmd;
  477.     pmd_val(pmd) = __virt_to_phys((unsigned long)ptep) | _PAGE_USER_TABLE;
  478.     return pmd;
  479. }
  480.  
  481. extern __inline__ pmd_t mk_kernel_pmd(pte_t *ptep)
  482. {
  483.     pmd_t pmd;
  484.     pmd_val(pmd) = __virt_to_phys((unsigned long)ptep) | _PAGE_KERNEL_TABLE;
  485.     return pmd;
  486. }
  487.  
  488. #if 1
  489. #define set_pmd(pmdp,pmd) processor.u.armv3v4._set_pmd(pmdp,pmd)
  490. #else
  491. extern __inline__ void set_pmd(pmd_t *pmdp, pmd_t pmd)
  492. {
  493.     *pmdp = pmd;
  494.     __flush_pte_to_ram(pmdp);
  495. }
  496. #endif
  497.  
  498. extern __inline__ unsigned long pmd_page(pmd_t pmd)
  499. {
  500.     return __phys_to_virt(pmd_val(pmd) & 0xfffffc00);
  501. }
  502.  
  503. /* to find an entry in a kernel page-table-directory */
  504. #define pgd_offset_k(address) pgd_offset(&init_mm, address)
  505.  
  506. /* to find an entry in a page-table-directory */
  507. extern __inline__ pgd_t * pgd_offset(struct mm_struct * mm, unsigned long address)
  508. {
  509.     return mm->pgd + (address >> PGDIR_SHIFT);
  510. }
  511.  
  512. /* Find an entry in the second-level page table.. */
  513. #define pmd_offset(dir, address) ((pmd_t *)(dir))
  514.  
  515. /* Find an entry in the third-level page table.. */
  516. extern __inline__ pte_t * pte_offset(pmd_t * dir, unsigned long address)
  517. {
  518.     return (pte_t *) pmd_page(*dir) + ((address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1));
  519. }
  520.  
  521. extern unsigned long get_small_page(int priority);
  522. extern void free_small_page(unsigned long page);
  523.  
  524. /*
  525.  * Allocate and free page tables. The xxx_kernel() versions are
  526.  * used to allocate a kernel page table - this turns on ASN bits
  527.  * if any.
  528.  */
  529.  
  530. #ifndef __SMP__
  531. extern struct pgtable_cache_struct {
  532.     unsigned long *pgd_cache;
  533.     unsigned long *pte_cache;
  534.     unsigned long pgtable_cache_sz;
  535. } quicklists;
  536.  
  537. #define pgd_quicklist (quicklists.pgd_cache)
  538. #define pmd_quicklist ((unsigned long *)0)
  539. #define pte_quicklist (quicklists.pte_cache)
  540. #define pgtable_cache_size (quicklists.pgtable_cache_sz)
  541. #else
  542. #error Pgtable caches have to be per-CPU, so that no locking is needed.
  543. #endif
  544.  
  545. extern pgd_t *get_pgd_slow(void);
  546.  
  547. extern __inline__ pgd_t *get_pgd_fast(void)
  548. {
  549.     unsigned long *ret;
  550.  
  551.     if((ret = pgd_quicklist) != NULL) {
  552.         pgd_quicklist = (unsigned long *)(*ret);
  553.         ret[0] = ret[1];
  554.         pgtable_cache_size--;
  555.     } else
  556.         ret = (unsigned long *)get_pgd_slow();
  557.     return (pgd_t *)ret;
  558. }
  559.  
  560. extern __inline__ void free_pgd_fast(pgd_t *pgd)
  561. {
  562.     *(unsigned long *)pgd = (unsigned long) pgd_quicklist;
  563.     pgd_quicklist = (unsigned long *) pgd;
  564.     pgtable_cache_size++;
  565. }
  566.  
  567. extern __inline__ void free_pgd_slow(pgd_t *pgd)
  568. {
  569.     free_pages((unsigned long) pgd, 2);
  570. }
  571.  
  572. extern pte_t *get_pte_slow(pmd_t *pmd, unsigned long address_preadjusted);
  573. extern pte_t *get_pte_kernel_slow(pmd_t *pmd, unsigned long address_preadjusted);
  574.  
  575. extern __inline__ pte_t *get_pte_fast(void)
  576. {
  577.     unsigned long *ret;
  578.  
  579.     if((ret = (unsigned long *)pte_quicklist) != NULL) {
  580.         pte_quicklist = (unsigned long *)(*ret);
  581.         ret[0] = ret[1];
  582.         pgtable_cache_size--;
  583.     }
  584.     return (pte_t *)ret;
  585. }
  586.  
  587. extern __inline__ void free_pte_fast(pte_t *pte)
  588. {
  589.     *(unsigned long *)pte = (unsigned long) pte_quicklist;
  590.     pte_quicklist = (unsigned long *) pte;
  591.     pgtable_cache_size++;
  592. }
  593.  
  594. extern __inline__ void free_pte_slow(pte_t *pte)
  595. {
  596.     free_small_page((unsigned long)pte);
  597. }
  598.  
  599. /* We don't use pmd cache, so this is a dummy routine */
  600. extern __inline__ pmd_t *get_pmd_fast(void)
  601. {
  602.     return (pmd_t *)0;
  603. }
  604.  
  605. extern __inline__ void free_pmd_fast(pmd_t *pmd)
  606. {
  607. }
  608.  
  609. extern __inline__ void free_pmd_slow(pmd_t *pmd)
  610. {
  611. }
  612.  
  613. extern void __bad_pmd(pmd_t *pmd);
  614. extern void __bad_pmd_kernel(pmd_t *pmd);
  615.  
  616. #define pte_free_kernel(pte)    free_pte_fast(pte)
  617. #define pte_free(pte)        free_pte_fast(pte)
  618. #define pgd_free(pgd)        free_pgd_fast(pgd)
  619. #define pgd_alloc()        get_pgd_fast()
  620.  
  621. extern __inline__ pte_t * pte_alloc_kernel(pmd_t *pmd, unsigned long address)
  622. {
  623.     address = (address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1);
  624.     if (pmd_none(*pmd)) {
  625.         pte_t *page = (pte_t *) get_pte_fast();
  626.  
  627.         if (!page)
  628.             return get_pte_kernel_slow(pmd, address);
  629.         set_pmd(pmd, mk_kernel_pmd(page));
  630.         return page + address;
  631.     }
  632.     if (pmd_bad(*pmd)) {
  633.         __bad_pmd_kernel(pmd);
  634.         return NULL;
  635.     }
  636.     return (pte_t *) pmd_page(*pmd) + address;
  637. }
  638.  
  639. extern __inline__ pte_t * pte_alloc(pmd_t * pmd, unsigned long address)
  640. {
  641.     address = (address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1);
  642.  
  643.     if (pmd_none(*pmd)) {
  644.         pte_t *page = (pte_t *) get_pte_fast();
  645.  
  646.         if (!page)
  647.             return get_pte_slow(pmd, address);
  648.         set_pmd(pmd, mk_user_pmd(page));
  649.         return page + address;
  650.     }
  651.     if (pmd_bad(*pmd)) {
  652.         __bad_pmd(pmd);
  653.         return NULL;
  654.     }
  655.     return (pte_t *) pmd_page(*pmd) + address;
  656. }
  657.  
  658. /*
  659.  * allocating and freeing a pmd is trivial: the 1-entry pmd is
  660.  * inside the pgd, so has no extra memory associated with it.
  661.  */
  662. extern __inline__ void pmd_free(pmd_t *pmd)
  663. {
  664. }
  665.  
  666. extern __inline__ pmd_t *pmd_alloc(pgd_t *pgd, unsigned long address)
  667. {
  668.     return (pmd_t *) pgd;
  669. }
  670.  
  671. #define pmd_free_kernel        pmd_free
  672. #define pmd_alloc_kernel    pmd_alloc
  673.  
  674. extern __inline__ void set_pgdir(unsigned long address, pgd_t entry)
  675. {
  676.     struct task_struct * p;
  677.     pgd_t *pgd;
  678.  
  679.     read_lock(&tasklist_lock);
  680.     for_each_task(p) {
  681.         if (!p->mm)
  682.             continue;
  683.         *pgd_offset(p->mm,address) = entry;
  684.     }
  685.     read_unlock(&tasklist_lock);
  686.     for (pgd = (pgd_t *)pgd_quicklist; pgd; pgd = (pgd_t *)*(unsigned long *)pgd)
  687.         pgd[address >> PGDIR_SHIFT] = entry;
  688. }
  689.  
  690. extern pgd_t swapper_pg_dir[PTRS_PER_PGD];
  691.  
  692. /*
  693.  * The sa110 doesn't have any external MMU info: the kernel page
  694.  * tables contain all the necessary information.
  695.  */
  696. extern __inline__ void update_mmu_cache(struct vm_area_struct * vma,
  697.     unsigned long address, pte_t pte)
  698. {
  699. }
  700.  
  701. #define SWP_TYPE(entry) (((entry) >> 2) & 0x7f)
  702. #define SWP_OFFSET(entry) ((entry) >> 9)
  703. #define SWP_ENTRY(type,offset) (((type) << 2) | ((offset) << 9))
  704.  
  705. #endif /* __ASM_PROC_PAGE_H */
  706.